package cn.rs.lvt.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.rs.framework.core.web.page.PageParam;
import cn.rs.framework.core.web.page.PageResult;
import cn.rs.framework.core.web.response.ResultBean;
import cn.rs.jpa.extension.util.BlazebitTool;
import cn.rs.lvt.dto.AccessTokenPageDTO;
import cn.rs.lvt.entity.AccessTokenEntity;
import cn.rs.lvt.entity.QAccessTokenEntity;
import cn.rs.lvt.entity.QUserEntity;
import cn.rs.lvt.entity.UserEntity;
import cn.rs.lvt.entityview.TokenEntityView;
import cn.rs.lvt.entityview.TokenEntityView2;
import cn.rs.lvt.service.IAccessTokenService;
import com.blazebit.persistence.CriteriaBuilder;
import com.blazebit.persistence.JoinType;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Tag(name = "accessToken 相关接口")
@RequestMapping("/accessToken")
public class AccessTokenResource {

    @Autowired
    private IAccessTokenService iAccessTokenService;

    @PostMapping("add")
    @Operation(summary = "新增")
    public ResultBean<AccessTokenEntity> add(@RequestBody AccessTokenEntity entity) {
        iAccessTokenService.save(entity);
        return ResultBean.success();
    }

    @PostMapping("batchDel")
    @Operation(summary = "根据 tokenID 批量删除")
    public ResultBean<Boolean> batchDel(@RequestBody List<String> id) {
        iAccessTokenService.removeBatch(id);
        return ResultBean.success();
    }

    @PutMapping("updateById")
    @Operation(summary = "根据 tokenID 更新")
    public ResultBean<Boolean> updateById(@RequestBody AccessTokenEntity entity) {
        iAccessTokenService.update(entity);
        return ResultBean.success();
    }

    @GetMapping("getById")
    @Operation(summary = "根据 tokenID 查询")
    public ResultBean<AccessTokenEntity> getById(@RequestParam String id) {
        iAccessTokenService.getById(id);
        return ResultBean.success();
    }

    @GetMapping("page1")
    @Operation(summary = "分页查询 - 用blazebit查询简单分页")
    public ResultBean<PageResult<AccessTokenEntity>> page1(
            @ParameterObject PageParam pageParam,
            @ParameterObject AccessTokenPageDTO dto
    ) {
        return ResultBean.success(iAccessTokenService.blazebitPageSimple(pageParam, criteriaBuilder -> {
            // TODO 封装 dto
            if (CollUtil.isNotEmpty(dto.getId())) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getId)).in(dto.getId());
            }
            if (StrUtil.isNotBlank(dto.getUid())) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getUid)).eq(dto.getUid());
            }
            if (dto.getStart() != null) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getCreateTime)).ge(dto.getStart());
            }
            if (dto.getEnd() != null) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getCreateTime)).le(dto.getEnd());
            }
        }));
    }

    /**
     * page2- 当实体类里没有记录@ManyToOne等关联关系时, 需要在@EntityView注解的类里体现
     * @param pageParam
     * @param dto
     * @return
     */
    @GetMapping("page2")
    @Operation(summary = "分页查询 - 用blazebit查询复杂分页, 多表join, 自动映射查询结果等")
    public ResultBean<PageResult<TokenEntityView>> page2(
            @ParameterObject PageParam pageParam,
            @ParameterObject AccessTokenPageDTO dto
    ) {
        QUserEntity qUser = QUserEntity.userEntity;
        return ResultBean.success(iAccessTokenService.blazebitPageComplex(pageParam, criteriaBuilder -> {

            // 在@EntityView里定义好映射关系, 会自动生成join关系
//            criteriaBuilder
//                    .from(AccessTokenEntity.class, "accessTokenEntity")
//                    .leftJoinOn(UserEntity.class, "userEntity")
//                    .setOnExpression("accessTokenEntity.uid = userEntity.id")
//            ;

            // TODO 封装 dto
            if (CollUtil.isNotEmpty(dto.getId())) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getId)).in(dto.getId());
            }
            if (StrUtil.isNotBlank(dto.getUid())) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getUid)).eq(dto.getUid());
            }
            if (dto.getStart() != null) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getCreateTime)).ge(dto.getStart());
            }
            if (dto.getEnd() != null) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getCreateTime)).le(dto.getEnd());
            }
        }, TokenEntityView.class));
    }

    /**
     * page3 - 当实体类里记录了一对一或一对多等关系后, @EntityView视图类里不需要体现关联关系
     * @param pageParam
     * @param dto
     * @return
     */
    @GetMapping("page3")
    @Operation(summary = "分页查询 - 用blazebit查询复杂分页, 多表join, 自动映射查询结果等")
    public ResultBean<PageResult<TokenEntityView2>> page3(
            @ParameterObject PageParam pageParam,
            @ParameterObject AccessTokenPageDTO dto
    ) {
        return ResultBean.success(iAccessTokenService.blazebitPageComplex(pageParam, criteriaBuilder -> {

            // TODO 封装 dto
            if (CollUtil.isNotEmpty(dto.getId())) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getId)).in(dto.getId());
            }
            if (StrUtil.isNotBlank(dto.getUid())) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getUid)).eq(dto.getUid());
            }
            if (dto.getStart() != null) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getCreateTime)).ge(dto.getStart());
            }
            if (dto.getEnd() != null) {
                criteriaBuilder.where(BlazebitTool.getFieldExpression(AccessTokenEntity::getCreateTime)).le(dto.getEnd());
            }
        }, TokenEntityView2.class));
    }

    @GetMapping("page4")
    @Operation(summary = "分页查询-用queryDSL的Q类")
    public ResultBean<PageResult<AccessTokenEntity>> page4(
            @ParameterObject PageParam pageParam,
            @ParameterObject AccessTokenPageDTO dto
    ) {
        QAccessTokenEntity q = QAccessTokenEntity.accessTokenEntity;
        return ResultBean.success(iAccessTokenService.querydslPage(pageParam, query -> {
            BooleanBuilder builder = new BooleanBuilder();
            if(CollUtil.isNotEmpty(dto.getId())) {
                builder.and(q.id.in(dto.getId()));
            }
            if (StrUtil.isNotBlank(dto.getUid())) {
                builder.and(q.uid.eq(dto.getUid()));
            }
            if (dto.getStart() != null) {
                builder.and(q.createTime.goe(dto.getStart()));
            }
            if (dto.getEnd() != null) {
                builder.and(q.createTime.lt(dto.getEnd()));
            }
            query.where(builder);
        }, Projections.constructor(AccessTokenEntity.class,q.id, q.uid)));
    }

}
